Magic Disk 64

home to index to html: KURS-FLOPPY INTERN.html
          Floppy-Programmierung         
               für Profis               
 Bevor wir loslegen möchte ich mich kurz
vorstellen: Ich heiße Frank Boldewin und
besitze bin seit  1985  Besitzer  meines
C64'ers!  Seit etwa zwei Jahren versuche
ich die letzten  Geheimnisse  der Floppy
zu ergründen und bin auch heute noch be-
geistert bei der Sache!                 
Da sie das erforderliche Basiswissen be-
reits von meinen Kollegen Uli Baster und
seinem überaus ausführlichen Floppy-Kurs
vermittelt bekommen haben,  möchte  ich,
um lästige Wiederholungen zu vermeiden, 
mit meinem Kurs ganz andere Schwerpunkte
setzen.  Wie werden uns in erster Linie 
auf die Programmierung von Routinen kon-
zentrieren,die allgemein als kompliziert
angesehen werden,wie z.B.ein Fast-Loader
oder ein Kopierschutz.                  
  Sie brauchen keine Angst zu haben, daß
dieser Kurs nur für  Profis gemacht ist,
die soweit fortgeschritten sind, daß man
ihnen kaum noch etwas beibringen kann.  
 Jede  Routinen  die  ich ihnen im Laufe
dieses Kurses vorstelle, wird genaustens
erklärt,so daß sie gegen Ende des Kurses
ganz  allein  in  der  Lage  sein werden
ihren eigenen Fast-Loader zu schreiben. 
Floppy Programmierer werden sich schwer-
tun, um in den Besitz geeigneter Lektüre
zu gelangen. Verglichen mit dem geradezu
üppigen Literatur Angebot,   daß für den
C64 vorzufinden ist,kann man das derzeit
für die  Floppy  vorliegende Angebot nur
als mager bezeichnen.  Deshalb werde ich
in dieser und den nächsten Ausgaben ver-
suchen, Ihnen die  Kunst  des Floppypro-
grammierens von Grund auf zu vermitteln!
Anhand von vielen Beispielen, deteilier-
ten  Erklärungen  und  unter  Vermeidung
langatmiger theoretischer Beschreibungen
dürfte es eigentlich kein  Problem  sein
ans gewünschte Ziel zu gelangen.        
Zunächst aber eine kleine Übersicht über
den Inhalt des gesamten Kurses.         
              Inhalt:                   
Teil 1: 1.Block Befehle                 
        2.User Befehle                  
        3.Memory Befehle                
        4.der VIA 6522                  
Teil 2: 1.die BAM                       
        2.Aufbau von Files              
        3.Laden+Speichern von Files     
        4.Zero-Page Adressen            
Teil 3: 1.Fehlerkanal lesen             
        2.Lesen+Schreiben eines Blocks  
        3.Jobspeicher                   
        4.Jobcodes                      
Teil 4: 1.die Floppy Zero-Page          
        2.SYNC Markierungen             
        3.Pruefsummen                   
        4.Aufbau einer formatierten Disk
Teil 5: 1.Whole Load+Save               
        2.DIR Routine                   
        3.Kopierschutz                  
Teil 6: 1.Diskcontroller                
        2.Buscontroller                 
        3.Fastload                      
 Soweit zum  Kursinhalt.  In diesem Teil
wollen  noch  einmal  sämtliche  Floppy-
Befehle  zusammenfassen  und  anhand von
Basic Routinen kurz erläutern.          
In dem Nächsten un allen weiteren Kursen
muß ich leider zum besseren  Verständnis
der  abgedruckten  Programme,  etwas Er-
fahrung im  Umgang  mit  einem Assembler
oder  einem  Monitor  voraussetzen, denn
die  Floppy  lediglich  in Basic zu pro-
grammieren ist für ein Vorhaben, wie das
Unsere praktisch unmöglich.    In diesem
Teil des  Kurses  kommt es lediglich da-
rauf an,  den Sinn in die Anwendungsmög-
lichkeiten, der Floppy Kommandos zu ver-
deutlichen, da wir nicht noch einmal auf
jede Einzelheit eingehen können.     Die
Profis unter Ihnen werden erst,  in  den
nächsten Teilen auf Ihre  Kosten kommen,
wenn  wir  mit  einem  (extra für diesen
Kurs entwickelten) Machinensprachmonitor
der Floppy auf den Leib rücken.         
 Nach dieser  Vorrede,   möchten wir nun
endlich mit dem  eigentlichen  Kurs  be-
ginnen.                                 
            Die BLOCK-Befehle:          
            ------------------          
 Voraussetzung für die sachgemäße Anwen-
dung dieser Befehle ist die Kenntnis des
Diskettenaufbaus.   Dieser wurde bereits
in  dem  Anfängerkurs  deteilliert   be-
sprochen.                               
       Der BLOCK-READ Befehl (B-R)      
       ---------------------------      
 Angenommen  Sie  möchten   gerne  einen
einzelnen Block von der Diskette lesen! 
Kein Problem, denn  Abhilfe  schafft der
BLOCK-READ  Befehl!  Er bewirkt, daß  in
einen vorher definierten Puffer der  ge-
wünschte Track+Sektor geschrieben wird! 
Syntax:                                 
print# Fn,"b-r";Cn;Dn;T;S               
Erklaerung der Abkuerzungen:            
Fn (Filenumber 1-127)                   
Cn (Channelnumber 2-14)                 
Dn (Drivenumber 0)                      
T+S(Track+Sektor)                       
Wollen wir also Track 18,Sektor 0 lesen,
dann tippen Sie bitte  folgende  Befehle
ein:                                    
       OPEN1,8,2,"#"                    
       OPEN15,8,15                      
       PRINT#15,"B-R 2 0 18 0"          
       CLOSE1                           
       CLOSE15                          
 Nachdem dieser Befehl ausgeführt wurde,
fragen  Sie  sich  sicher,  weshalb  die
'OPEN' Befehle am Anfang.               
       OPEN1,8,2,"#"                    
Ist notwendig,da vor jedem Direktzugriff
ein  Puffe r reserviert werden muß.  Wir
haben uns einen beliebigen gewählt, weil
es in dem Fall egal war! Wollen wir aber
einen bestimmten Puffer ansprechen, z.B.
Puffer 1, dann geben sie bitte folgendes
ein:                                    
       OPEN1,8,2,"#1"                   
Syntax:                                 
open Fn,Dr,Cn,"#"                       
Bedeutungen der Abkuerzungen:           
Fn (Filenumber 1-127)                   
Dr (Devicenumber 8-11)                  
Cn (Channelnumber 2-14)                 
Fehlt  also  nur  noch der andere 'OPEN'
Befehl.                                 
        OPEN15,8,15                     
Ist notwendig, um den  Kommandokanal  zu
öffnen, da alle BLOCK- MEMORY- und USER-
Befehle Kommandos sind.                 
 Zum B-R selbst muß man sagen,  daß sich
leider damit das erste Byte eines Blocks
nicht lesen läßt.   Im Laufe dieses Kurs
werden wir  aber  noch einen anderen Be-
fehl kennenlernen,  der auch dieses Byte
lesen kan.                              
 Ich möchte jedoch noch mal kurz auf die
Kanäle der Floppy zurückgreifen, da dort
dort sicherlich noch einige Fragen offen
geblieben sind.                         
 Wahrscheinlich haben sie sich schon ge-
fragt, warum man erst ab   Kanal 2   mit
dem  Block-Befehl  arbeiten kann.   Dies
liegt daran, weil die Kanäle 0+1 für das
Laden  und  Speichern  schon   verwendet
werden.  Der Kanal  15  wird benötigt um
bestimmte Kommandos auszuführen,wie z.B.
format,  scratch,  init usw.!           
Das gilt natürlich auch für alle anderen
Befehle!                                
 Schauen  wir  uns als nächstes doch mal
den BLOCK-WRITE Befehl an.              
         Der BLOCK-WRITE Befehl (B-W)   
         ----------------------------   
 Dieser Befehl ist das entsprechende Ge-
genstück zum B-R.   Hierbei wird der In-
halt eines  Buffers auf Diskette zurück-
geschrieben.                            
Syntax:                                 
print# Fn,"b-w";Cn;Dn;;T;S              
Beispiel:                               
        OPEN1,8,2,"#"                   
        OPEN15,8,15                     
        PRINT#15,"B-W 2 0 18 0"         
        CLOSE1                          
        CLOSE15                         
 Man sieht schon das er in der  Befehls-
folge fast identisch mit dem  B-R Befehl
ist.   Eine ausführliche Erläuterung der
Befehlsfolge erübrigt sich daher.       
         der BUFFER-POINTER (B-P)       
         ------------------------       
Nehmen wir einmal an Sie möchten anstatt
eines ganzen Blocks, nur  ein  einzelnes
Byte aus der Floppy heraus lesen.   Kein
Problem,  den  Abhilfe  schafft  der B-P
Befehl.                                 
Dazu muß man wissen,daß ein jeder Buffer
einen  bestimmten  Pointer  besitzt.  In
diesen  Pointer  kann man nun eine  Zahl
zwischen 0 und 255 schreiben. Diese Zahl
sagt der Floppy welches Byte sie aus der
Floppy  holen  soll.  Natürlich  muß die
Floppy auch wissen aus welchem Track und
Sektor.  Zum  besseren  Verständnis  nun
wieder ein kleines Beispiel mit der ent-
sprechenden Syntax dazu!                
Syntax:                                 
Print# Fn,"b-p";Cn;Position             
Beispiel:                               
        OPEN1,8,2,"#0"                  
        OPEN15,8,15                     
        PRINT#15,"B-R 2 0 18 0"         
        PRINT#15,"B-P 2 2"              
        GET#1,A$                        
        A=ASC(A$+CHR$(0))               
        PRINT A                         
        CLOSE1                          
        CLOSE15                         
 Wie Sie  sehen lesen wir den Directory-
Block in  den  Floppy-Puffer  und  holen
uns das zweite Byte  dieses  Sektors mit
dem B-P Befehl.  Anschliessend holen wir
uns durch den 'GET'-Befehl das Byte über
den Kommando-Kanal ab. Nun kann das Byte
auf dem  Bildschirm  ausgegeben  werden!
Dies geschieht mit Hilfe von 'PRINT A'. 
 Dieses gelesene Byte hat eine besondere
Funktion auf die ich später im Kurs noch
zu sprechen komme!                      
     Der BLOCK-EXECUTE Befehl (M-E)     
     ------------------------------     
 Der B-E Befehl hat die                 
selbe Syntax wie der B-R Befehl.   Seine
zusätzliche Eigenschaft ist aber, daß er
den geladenen Block im Puffer der Floppy
als Maschinenprogramm ausführt.   Es er-
übrigt sich deshalb die Syntax zu diesem
Befehl zu erläutern,  da er sich wie der
B-R Befehl verhält!                     
B-A(Block Allocate) und B-F(Block-Free):
 Stellen sie sich vor Sie haben ein Pro-
gramm  geschrieben, daß bestimmte  Daten
verwaltet.   Für diese Daten möchten Sie
jedoch  nicht  extra  Files  anlegen und
schreiben  die Daten auf einen einzelnen
Sektor, mithilfe des Direktzugriffs.    
 Alles schön und gut, aber was passiert,
wenn man jetzt noch zusätzlich ein  Pro-
gramm auf die selbe  Diskette  speichern
möchte? Sehr warscheinlich werden unsere
Daten überschrieben,   da sie nicht ent-
sprechend gekennzeichnet sind!    Um sie
nun zu kennzeichnen muss                
man also den B-A Befehl verwenden!      
Wir wollen nun  T 23, S 1  kennzeichnen!
Syntax:                                 
print# Fn,"b-a";Dn;T;S                  
Beispiel:                               
print# Fn,"b-a 0 23 1"                  
 Wollen wir den Sektor wieder freigeben,
so  benutzen wir den  B-F  Befehl!  Die 
Syntax zum diesem  Befehl  ist die selbe
wie beim B-A Befehl.                    
           Die MEMORY-BEFEHLE           
           ------------------           
 Als  nächstes  möchte  ich mich nun den
MEMORY-Befehlen zuwenden.  Diese Befehle
haben eine ähnliche  Bedeutung  wie  der
'PEEK'  und  'POKE' Befehl in Basic, nur
mit dem  wesentlichen  Unterschied,  daß
nicht  die  Bytes  im  Computerspeicher,
sondern die  im  Floppyspeicher  gelesen
und beschrieben werden können.          
      Der MEMORY-READ Befehl (M-R)      
      ----------------------------      
 Mit diesem  Befehl  kann jede beliebige
Speicherstelle  der  Floppy   ausgelesen
werden.Verglichen mit den Block-Befehlen
sind die  Memory-Befehle etwas einfacher
zu  handhaben, wie Ihnen das folgen Bei-
spiel geleich zeigen wird.              
Syntax:                                 
print#Fn,"M-R" Chr$(LB) Chr$(HB) chr$(B)
LB=Low Byte Adresse                     
HB=Hi  "    "                           
B =Anzahl der Bytes                     
Beispiel:                               
OPEN 15,8,15                            
PRINT#15,"M-R" chr$(18) chr$(0) chr$(2) 
GET#15,a$,b$                            
PRINT a$;b$                             
CLOSE1                                  
 Mit diesem Befehl wurden die 'ID' Bytes
des letzten  Lesevorgangs herausgelesen.
Diese  stehen  in  der  Zeropage  in den
Speicherstellen 18 und 19.     Wir sehen
schon,  daß auch hier die entsprechenden
Werte mit 'get' abgeholt werden.        
      Der MEMORY-WRITE Befehl (M-W)     
      -----------------------------     
 Der  M-W Befehl  ist das entsprechenden
Gegenstück zum M-R Befehl.  Mit ihm kann
theoretisch  jede  beliebige   Speicher-
stelle beschrieben werden.   Theoretisch
deshalb,  weil immer nur der Speicherbe-
reich eines Rechners  beschrieben werden
kann,   in dem sich auch tatsächlich RAM
befindet.  Wie  der  Speicher der Floppy
im  einzelnen  aufgebaut  ist,  wird  am
Schluß des Kursteils erläutert.         
 Auf die folgende Weise, können sie eine
oder mehrere Daten in den  Floppy-Puffer
schreiben.                              
Syntax:                                 
print#Fn,"M-W" Chr$(LB) Chr$(HB) Chr$(B)
Chr$(Data1) Chr$(Data2).........        
open 15,8,15                            
print#15,"M-R" chr$(18) chr$(0) chr$(2) 
get#15,a$,b$                            
print a$;b$                             
close1                                  
     Der MEMORY-EXECUTE Befehl (M-E)    
     -------------------------------    
Der M-E Befehl entspricht dem SYS-Befehl
in Basic. Mit ihm lassen sich Maschinen-
programme im Speicher der Floppy starten
Man benutzt den 'M-E' sehr häufig im Zu-
sammenhang mit dem 'M-W' Befehl,   wobei
der 'M-W' die Bytefolge einer  spezielle
Maschinenroutine  (Fast-Loader  oder Ko-
pierschutz)in den Floopy-Puffer schreibt
von wo aus, sie mit einem  'M-E'  Befehl
gestartet oder initialisiert wird.      
 Die Syntax zum Starten einer Maschinen-
routine lautet:                         
Syntax:                                 
print#Fn,"M-E" Chr$(LB) Chr$(HB)        
             Der USER Befehl            
             ---------------            
 Nachdem wir auch diese Reihe besprochen
haben,   wollen uns nun dem wohl am häu-
figsten benutzten Befehlen zu, den'USER'
Befehlen.                               
Beginnen wir mit dem 'U1'.Mit diesem Be-
fehl läßt sich ein Sektor               
in einen beliebigen Puffer lesen!Mit dem
'U1'  kann  man  auch  den  ganze Puffer
lesen,  was  ja bei dem B-R Befehl nicht
der Fall war,   da er das erste Byte des
Sektors nicht lesen konnte.Auch der'M-R'
besitzt diese Fähigkeit! Nun schnell zur
Syntax!                                 
Syntax:                                 
print#Fn"u1";Cn;Dn;T;S                  
Beispiel:                               
print#15"u1 2 0 18 0"                   
 mit dem  'U2'  Befehl lassen sich Daten
auf die Diskette zurueckschreiben! Da er
die gleiche Syntax besitzt wie  der 'U1'
möchte ich nicht länger  darauf eingehen
und mich den U 3-8 zuwenden!            
 Sie entsprechen dem 'M-E'!  Der Vorteil
ist. Daß 'LO+HI' Byte nicht mehr angege-
ben werden müssen,da jeder User 3-8 eine
vorgegebene Startadresse hat,die hier in
Tabellarischer Form wiedergegeben sind: 
Befehl - Start                          
  U3     $0500                          
  U4     $0503                          
  U5     $0506                          
  U6     $0509                          
  U7     $050c                          
  U8     $050f                          
 Der Nachteil der U3-8 Befehle ist,  daß
lediglich  6  verschiedene Start-Befehle
für ihr Programm  zur  Verfügung stehen.
Es sei deshalb ihnen überlassen, ob sie 
die  'U3-8' oder lieber den 'M-E' Befehl
benutzen (bei dem sie ein Programm an   
jeder beliebigen Adresse starten können)
 Der  'U9'  Befehl  ist  in der Lage die
Floppystation  zwischen  dem C64(9+) und
dem VC20(9-) Betrieb umzuschalten!      
Mit U: wird ein Reset in der Floppy aus-
geloesst!                               
  Zum Schluß dieses Kursteils möchte ich
noch  schnell  die wichtigsten Speicher-
inhalte des VIA6522 angeben:            
$0000 - Zero Page                       
$0100 - Stack                           
$0145 - Page 1                          
$0200 - Befehlspuffer                   
$0228 - Page 2                          
$0300 - Puffer 0 (Hauptspeicher)        
$0400 - Puffer 1 (Dirpuffer 2)          
$0500 - Puffer 2 (Benutzerpuffer)       
$0600 - Puffer 3 (Dirpuffer 1)          
$0700 - Puffer 4 (BAM)                  
$0800 - nicht benutzt                   
$1800 - serieller Bus                   
$1c00 - Laufwerkssteuerung              
$c000 - 16 KByte ROm Betriebsystem      
Okay damit wären wird mit der Einführung
am Ende.                                
Im nächsten Kursteil ist die  professio-
nelle Programmierung der Floppy dar, bei
der  auch  die  Assembler-Freaks   unter
ihnen auf ihre Kosten kommen werden.    
Bis nächsten Monat dann also!      (FB) 
               FLOPPY INTERN            
                  (Teil 2)              
 Willkommen  zum  zweiten  Teil  unseres
Floppykurses!                           
Da im ersten Teil dieses Kurses so ziem-
lich alle Möglichkeiten angesprochen und
abgehandelt  wurden  die bei der Floppy-
programmierung  von  BASIC aus zu reali-
sieren sind,wollen wir ab diesem Kurs in
Assembler weiterprogrammieren,    da die
Routinen, die wir im Laufe der Zeit ent-
wickeln wollen,  in Höchstgeschwindlich-
keit ablaufen sollen.                   
 Damit  dürfte  bereits gesagt sein, daß
dies  kein  reiner  Einsteigerkurs  sein
kann und soll. Erfahrungen im Ungang mit
einem  Monitor oder Assembler und Beher-
schung  der Maschinensprache sind erfor-
derlich.                                
Zur Programmierung der Floppy ist außer-
dem  noch  ein  ausgereifter Diskmonitor
erforderlich.Weil alle vorhandenen Disk-
monitore unseren  Ansprüchen  nicht ent-
sprachen,  hatten wir keine andere Wahl,
als uns hinzusetzen und einen eigenen zu
schreiben. Das  Ergebnis  unserer Arbeit
finden sie auf SEITE-1 dieser Ausgabe.Es
trägt die Bezeichnung "DISKPATCHER".  Da
er bereits in diesem  Kursteil eingesetz
wird, sollten sie sich möglichsr schnell
mit seinen Funktionen vertraut machen.  
 Die  Funktionen  werden im Laufe dieses
Kurses erklärt.                         
 Sollten  sie  bereits einen Diskmonitor
besitzen,mit dem sie gut zurechtskommen,
können sie selbstverstänstlich weiterbe-
nutzen.                                 
Doch nun zum eigentlichen Kurs.         
               Die BAM                  
               -------                  
 Gleich zu beginn wollen wir uns mit der
"BAM" der 1541 auseinandersetzen!       
 Die BAM ist der Sektorbelegungsplan der
Floppy und ist zu finden in Track 18 und
Sektor 0! Aufbau der BAM:               
Byte:   Bedeutung:                      
000     Tracknum.  fuer Directorybeginn 
001     Sektornum. "     "              
002     Formatkennzeichen (A)           
003     nur fuer 1571                   
004     Freie Sektoren TRACk 1          
005-007 Bitmuster Track 1               
        Bit=1 Sektor frei               
        Bit=0 Sektor belegt             
        Byte 005 - Belegung Sektor 0-7  
        "    006 - "        "      8-16 
        "    007 - "        "     17-23 
008-011 genauso wie Byte 4-7 nur Track 2
...                                     
140-166 HEADER (Diskname+ID)            
167-255 von der 1541 unbenutzt          
 Falls sie sich die BAM einmal näher an-
schauen wollen, können sie dies problem-
los  mit  dem  bereits  erwähnten "DISK-
PATCHER" tun, der ihnen Einblick in alle
Tracks und Sektoren der  Diskette gebie-
tet.                                    
Bei der Benutung vom DISKPATCHER sollten
sie  immer  Bedenken,  das  wirkürliches
Ändern  der Daten auf einer Diskette die
Vernichtng  aller Daten nach sich ziehen
kann.                                   
 Legen  Sie  sich daher zunaechst einmal
eine neu formatierte(Experiementier)Dis-
kette zu, da wir in nächster Zeit,  viel
mit Direktzugriffen zu tun haben werden.
Das  dabei auch mal was schiefgehen kann
ist auch verständlich!                  
Der DISKPATCHER bietet 4 Funktionen!    
1. Patchen der Diskette                 
2. Directory anzeigen                   
3. Floppykommandos senden (s;n;i;r;etc.)
4. Verlassen des Menues                 
Da die Funktionen 2-4 sich praktisch von
selbst  erklären,  wollen wir uns einmal
den Patcher selbst zur Brust nehmen!    
Drückt man die Taste 1, dann gelangt man
ins Patchermenue!                       
 Über die Tasten 'T' und 'S' lassen sich
TRACK und SEKTOR einstellen!  Sie werden
Hexadezimal dargestellt!  Wollen wir uns
nun Track 18, Sektor 0 anschauen, müssen
wir den Track auf $12=#18 einstellen!   
 Drücken Sie nun  'R'  um  den Sektor zu
lesen!   Es erscheint der Sektor auf dem
Bildschirm,  den  man  nun mit Taste 'E'
editieren kann, den Sektor beliebig ver-
ändern.                                 
 Durch  die  Tasten  CRSR-UP + CRSR-DOWN
können  Sie  den  Sektor hoch und runter
scrollen!                               
Durch drücken der RETURN-Taste,   kommen
wir aus dem Editmenue wieder raus.      
Die Funktion 'W' schreibt den gepatchten
(veraenderten) Sektor  auf  die Diskette
zurück! Durch 'Q' kommen Sie dann wieder
ins Hauptmenü!                          
       Der Aufbau der Directory         
       ------------------------         
Als nächstes möchte ich Sie mit dem Auf-
bau  eines   Directory-Blocks   vertraut
machen!                                 
In den einzelnen Directory-Blocks befin-
den sich  die  Filenamen,  die  sie beim
"Listen"  (LOAD"$",8)  der Directory er-
halten.  Sämtliche  Directory-Blocks be-
finden sich auf TRACK 18.      Der erste
Directory-Block befindet sich  auf TRACK
18 + SECTOR 1. Dieser Sector ist forgen-
dermaßen belegt.                        
Byte:   Bedeutung:                      
000-001 T+S fuer naechsten Dir-Block    
002-031 Eintrag File 1 (siehe unten)    
032-033 nicht benutzt                   
...                                     
...                                     
...                                     
...                                     
226-255 8.Eintrag                       
 Natürlich  möchten  Sie  nun wissen wie
wohl so ein Directoryeintrag aussieht!  
Byte:   Bedeutung:                      
000     Filetyp (PRG;REL;SEQ;USR;DEL;)  
001-002 T+S des Startsektors            
003-018 Filename                        
019-020 Start erster Side-Sektor (REL)  
021     Datensatzlaenge (REL)           
022-025 nicht benutzt                   
026-027 Zwischenspeicher fuer DEL T+S   
028-029 Blocklaenge des Files           
Die naechste Tabelle stellt den Aufbau  
eines Filetyp-Bytes dar:                
BIT: Bedeutung:                         
0    0                                  
1    0=DEL  0=SEQ  1=PRG  1=USR  0=REL  
2    0      0      0      0      1      
3    nicht benutzt                      
4    "                                  
5    "                                  
6    0=Normal  1=kein Scratch moeglich  
7    0=File noch offen                  
     1=File geschlossen                 
   Das Laden eines Files in Assembler   
   ----------------------------------   
 Nachdem  wir uns nun allerhand Tabellen
zu  Gemüte   geführt  haben  und wir die
grundlegenden Dinge kennen,  schauen wir
uns nun die  ROM-Routinen an,  mit denen
wir  den  Direktzugriff  auf  die Floppy
machen wollen!                          
 Nehmen  wir  einmal an, wir möchten ein
Programm laden! Kein Problem, werden Sie
jetzt sagen! Man tippt einfach,         
           LOAD"NAME",8,1:              
ein und schon wird das Programm geladen!
Wir wollen nun aber erkunden, was hinter
dem 'LOAD' Befehl steckt und schauen uns
die Assemblerroutine dazu an!           
 Sie  brauchen  hierzu  einen  SMON oder
einen ähnlichen Maschinensprachemonitor.
Hier also die Laderoutine:              
lda#$01  (Filenumer)                    
ldx#$08  (Geraeteadresse)               
ldy#$00  (Sekundaeradresse)             
jsr$fe00 (Fileparameter setzen)         
lda#$    (Laenge,max $10 Bytes)         
ldx#$    (LO-Byte Filename)             
ldy#$    (HI-Byte Filename)             
jsr$fdf9 (Filenamen setzen)             
lda#$00  (Load-Flag/1=Verify-Flag)      
ldx#$    (LO-Byte Startadresse)         
ldy#$    (HI-Byte Startadresse)         
jsr$f49e (Load)                         
rts                                     
Durch jsr $fe00 werden die Fileparameter
gesetzt,  damit  die  Floppy  weiß   von
welchem  Gerät Sie laden soll und wohin!
Ist die  Sekundäradresse  nähmlich  '0',
wird das Progamm an eine Adresse geladen
die Sie angeben! Ist Sie '1',dann werden
die  Informationen nach $0801 geladen wo
sich der  Basicstart  befindet,  um  die
Programme mit 'RUN' auszuführen!        
 Dieses  ist natürlich nur dann möglich,
wenn Sie eine Ansprungsadresse gepoked  
haben!                                  
 Der Filename des zu ladenden Files kann
sich irgenwo im Speicher ihres Rechners 
abgelegt sein. Um das entsprechende File
zu laden,  muß  der  Laderoutine im Akku
die Länge des Filenames und im X- und Y-
Register die  Adresse als LO+HI Byte an-
gegeben werden haben.                   
               lda #$10                 
               ldx #$80                 
               ldy #$30                 
               jsr $fdf9                
 Das bedeutet,daß der Filename $10 Bytes
lang  ist  und  bei der Adresse $3080 zu
finden ist.                             
 Durch  jsr $f49e wird dann das Programm
geladen! Um zu testen,  ob das File 'OK'
ist,macht man ganz einfach ein 'verify'.
Man muss nur  'lda#$01'  durch 'lda#$00'
ersetzen und schon wird geprüft,  ob ein
File ok oder defekt ist!                
Um dieses herauszufinden koennen Sie das
sogenannte Statusbyte abfragen!         
Es befindet sich in der Zeropage,bei der
Adresse $90 und hat folgende Belegung:  
Bit: Bedeutung:                         
1    Zeitueberschreitung bei IEC-Eingabe
2    "                   "   "  -Ausgabe
3-5  nur fuer die Datasette             
6    Uebertragung ist beendet und OK    
7    Geraet meldet sich nicht           
 Soll ein File an eine bestimmte Adresse
geladen werden,dann müssen sie folgendes
eingeben:                               
               lda #$00                 
               ldx #$40                 
               ldy #$10                 
               jsr $f49e                
 Das  File wird nun an die Adresse $1040
geladen,da in 'X' die LO- und in 'Y' die
HI-Adresse angegeben werden muß!        
 Die folgende Routine bietet eine andere
Möglichkeit ein File zu laden:          
    lda#$01                             
    ldx#$08                             
    ldy#$00                             
    jsr$fe00                            
    lda#$                               
    ldx#$                               
    ldy#$                               
    jsr$fdf9                            
    jsr$f34a   (open)                   
    ldx#$01    (chkin=auf               
    jsr$f20e    Empfang schalten)       
    jsr$ee13   (Startadresse            
    sta$ae      LO+HI                   
    jsr$ee13    holen und               
    sta$af      speichern)              
    ldy#$00     (Solange Bytes          
m02 jsr$ee13     vom Bus                
    sta($ae),y   holen                  
    inc$ae       bis die                
    bne$m01      Uebertragung           
    inc$af       komplett               
m01 bit$90       beendet                
    bvc$m02      ist)                   
    lda#$01      (close                 
    jsr$f291      File)                 
    jsr$f333     (clrchk)               
    rts                                 
 Nachdem das File mit jsr $f34a geöffnet
wurde,wird durch  LDX#$01 + JSR$f20e die
Floppy auf Empfang geschaltet!    Danach
liest  man  durch  die  'IECIN'  Routine
JSR $ee13 die  Startadresse  ein und be-
ginnt  dann das File  Byteweise zu Über-
tragen!                                 
 Zum  Schluss  wird  das File noch durch
LDA#$01 + JSR$f291 geschlossen,wobei die
'1' das zuerst geöffnete File schließt. 
 Wenn  man  also  zwei  Files öffnet muß
man  darauf  achten,  welches  File  man
schließen möchte!   Die Routine JSR$f333
verursacht einen CLRCHK und schaltet die
Floppy  wieder  zurÜck!  Durch  JSR$f49e
wird praktisch die Routine ab dem 'open'
Befehl ersetzt!                         
 Das Speichern eines Files in Assembler 
 -------------------------------------- 
Als nächstes wollen wir uns einmal eine 
Routine ansehen,die ein File speichert. 
Sie werden bemerken, daß der Aufbau der 
Speicherroutine  große  Ähnlichkeit mit 
dem der Laderoutine hat.                
lda#$01                                 
ldx#$08                                 
ldy#$00                                 
jsr$fe00                                
lda#$                                   
ldx#$                                   
ldy#$                                   
jsr$fdf9                                
ldx#$    (LO-Startadresse)              
ldy#$    (HI-Startadresse)              
stx$fb   (zwischen-                     
sty$fc    speichern)                    
lda#$fb (Pointer zeigt zur Startadresse)
ldx#$    (LO-Endadresse)                
ldy#$    (HI-Endadresse)                
jsr$f5dd (Save)                         
rts                                     
 Nachdem  die Fileparameter und der Name
übergeben  wurden,  wird  in x und y die
Startadresse angegeben,  um zu wissen ab
wo die Routine Speichern soll, und spei-
chern diese in $fb + $fc zwischen.      
 Danach  wird im Akku ein Zeiger auf die
Startadresse gelegt und in X und X  wird
die Endadresse übergeben.               
 Ist  das geschafft wird die Saveroutine
durch JSR$f5dd angesprungen.            
 Achten  Sie beim angeben der Endadresse
darauf,  daß Sie 1 Byte mehr angeben, da
sonst  das letzte Byte nicht gespeichert
wird!                                   
 Zum  Schluss  dieses  Kursteiles   noch
schnell eine  Tabelle mit Zero-Page-Adr.
unter denen die  Fileparameter  und  der
Name gespeichert werden:                
Adresse: Bedeutung:                     
$90      Status-Flag                    
$93      Flag fuer Load/Verify          
$98      Anzahl der offenen Files       
$99      Eingabegeraet fuer $ffcf       
$9a      Ausgabegeraet fuer $ffd2       
$ae/$af  Zaehler Filebytes-$Start       
$b7      Laenge Filename                
$b8      Aktive Filenummer              
$b9      Sekundaeradresse               
$ba      Geraeteadresse                 
$bb/$bc  Zeiger auf Filenamen           
 So, nun  haben wir es für heute  wieder
einmal geschafft. Ich hoffe es hat ihnen
Spass gemacht neue Erkenntnis  über  die
Floppy  zu  sammeln.                    
 Ich würde mich freuen,  Sie  auch  beim
nächsten Mal wieder begrüßen zu dürfen! 
Bis dahin, Ihr                          
              Frank Boldewin            
              FLOPPY-INTERN             
                 (Teil 3)               
 Willkommen  zur  dritten  Runde unseres
Floppykurses.                           
 Nachdem wir im letzten Teil das Status-
Flag  und  seine  Belegung  angesprochen
haben,  möchten  wir  Ihnen  diesmal ein
Programm vorstellen, daß den Fehlerkanal
ausließt.                               
    lda  #$00   ;Status-Flag            
    sta  $90    ;auf 0 setzen           
    lda  #$01   ;Filenummer             
    ldx  #$08   ;Geräteadresse          
    ldy  #$6f   ;Sekundäradresse        
    jsr  $fe00  ;Fileparameterjump      
    lda  #$00   ;Länge des              
    jsr  $fdf9  ;Filenamens=0           
    jsr  $f34a  ;Open                   
    lda  #$08   ;Geräteadresse          
    jsr  $ed09  ;auf Senden einstellen  
    lda  #$6f   ;Sekundäradresse        
    jsr  $edc7  ;übertragen             
m01 jsr  $ee13   ;Byte empfangen        
    jsr  $f1ca   ;ausgeben              
    bit  $90     ;wenn Bit6=0           
    bvc  $m01    ;dann nächstes Byte    
    lda  #$08   ;Senden durch           
    jsr  $edef  ;Untalk beenden         
    lda  #$01   ;Filenummer auf 1       
    jsr  $f291  ;und Close              
    rts                                 
 Beim Starten dieser Routine, gibt Ihnen
die  Floppy  entweder den entsprechenden
Fehler  aus  oder meldet, daß alles 'ok'
ist.Über die Subroutine "JSR $EE13" wird
der die Fehlermeldung Byte für Byte von 
der Floppy zum  Computer  übertragen und
auf dem Bildschirm ausgegeben.          
 Über Bit 6 kann geprüft werden,wann das
Ende der Fehlermeldung erreicht ist. Ist
Bit 6 = 0,  so bedeutet dies,  daß  noch
nicht alle Bytes der Fehlermeldung über-
tragen wurden.  Es  wird also solange zu
"JSR $EE31"  zurückgesprungen,  bis  die
die Floppy mit einem gesetzten Bit 6 das
Ende der Übertragung signalisiert.      
      Interne-Programmausführung        
      --------------------------        
 In dem  folgenden Abschnitt  wollen wir
uns mit der  ganz  besonderen  Fähigkeit
der Floopy befassen,  kleinere  Routinen
"intern" auszuführen.                   
 In den vorangegangenen Beispielen haben
wir  immer  nur einfache Floppy-Routinen
vom  C64  aus gestartet. Doch damit sind
die Möglichkeiten der Floppy noch  lange
nicht erschöpft.  Man kann zB auch ganze
Programme in die  Floppy transportieren,
die diese dann selbständig ausführt.Dies
ist  besonders  dann  wichtig,  wenn man
einen eigenen Schnellader oder einen Ko-
pierschutz schreiben will               
 Wie sie  vieleicht wissen,  handelt  es
sich bei der VC1541 um ein intelligentes
Diskettenlaufwerk mit eigenem  Prozessor
(6502), Speicherplatz (RAM und ROM)  und
Betriebsystem (DOS).   Dadurch wird kein
Speicherplatz und keine  Rechenzeit  vom
angeschlossenen  C64  benötigt.  Der C64
braucht der  Floppy lediglich Befehle zu
übermitteln,  die diese dann selbständig
ausführt.  Im Grunde genommen,  ist ihre
VC1541 nichts weiter  als  eine  zweiter
Computer neben ihrem C64. Sie haben also
nicht nur einen sondern gleich zwei Com-
puter auf ihrem  Schreibtisch  stehen.  
 Im  Normalbetrieb  muß  die Floppy drei
verschiedenen Aufgaben  gleichzeitig er-
ledigen. Dazu gehören:                  
1-Durchführung der  Datenübertragung von
  und zum C64.                          
2-die Interpretation der Befehle und die
  Verwaltung von Dateinen,der zugeordne-
  ten  Übertragungskanäle und der Block-
  buffer.                               
3-die  hardwaremäßige  Ansteuerung  der 
  Diskette.                             
Mit Hilfe einer ausgereiften IRQ-Technik
kann  die  Floppy  diese  drei  Aufgaben
praktisch gleichzeitig ausführen.       
 Nachdem wir bereits in den letzten bei-
den Kursen  auf  den Aufbau der Diskette
eingegangen sind,  wollen wir uns einmal
ansehen,  wie das DOS seine Aufgaben er-
ledigt.                                 
Selbverstündlich darf man beim Schreiben
von  eigenen  Routinen  im  Floppybuffer
auch  die  vorhandenen  Betetriebsystem-
routinen verwenden.  Ganz so einfach wie
im C64,  geht  es  bei der Floppy jedoch
nicht.                                  
  Das Betriebssystem der Floppy kann man
in zwei Teile unterteilen.Der erste Teil
ist das Hauptprogramm, das in einer End-
losschleife läuft.   Von diesem Teil aus
wird Hauptsächlich der serielle Bus ver-
waltet.   Fast alle Unterprogrammaufrufe
werden mit absoluten Sprüngen ausgeführt
und  müssen  somit  mit einem JMP-Befehl
zurück ins  Hauptprogramm  abgeschlossen
werden. Diese  Routinen  können nicht in
eigenen Programmen verwendet werden.    
 Der zweite Teil des Betriebsystems, ist
daher um so besser für eigene  Programme
zu verwenden, denn es handelt sich dabei
um ein  IRQ-Programm,  welches  auch als
"Jobschleife" bezeichnet wird.          
 Dieses Programm übernimmt die Lese- und
Schreiboperationen auf und von Diskette.
Bei jedem Interrupt werden die Speicher-
stellen $0 bis $5 der  (Floopy)Zeropage,
die  die   Schnittstelle,  zwischen  dem
Hauptprogramm herstellen, auf ihre Werte
überprüft.  Alle Werte,  die gleich oder
größer $80 sind werden als Befehle(Jobs)
behandelt und ausgeführt.   Jede  dieser
Speicherstellen  (Job-Speicher)  bezieht
sich auf  einen  bestimmten  Speicherbe-
reich.  Zusätzlich gehören zu jedem Job-
Speicher noch zwei Speicherstellen,  die
den  Track  und  den Sektor angeben, auf
die sich der Job(Befehl) bezieht.       
 Die  nachfolgende Tabelle, verdeutlicht
den Zusammenhang  zwischen  Job(Adresse)
Track-Sektorangabe und Speicherbereich. 
-----+-------+--------+-----------------
 JOB | TRACK | SEKTOR | SPEICHERBEREICH 
     |       |        |    (Buffer)     
 $00 |  $06  |  $07   |   $0300-$03ff   
 $01 |  $08  |  $09   |   $0400-$04ff   
 $02 |  $0a  |  $0b   |   $0500-$05ff   
 $03 |  $0c  |  $0d   |   $0600-$06ff   
 $04 |  $0e  |  $0f   |   $0700-$07ff   
 $05 |  $10  |  $11   |     kein RAM    
-----+-------+--------+-----------------
 Die nächste Tabelle zeigt die Bedeutung
der einzelnen Job-Codes.                
--------+-------------------------------
JOB-CODE|      AUFGABE                  
   $80  |Sektor lesen                   
   $90  |Sektor schreiben               
   $a0  |Sektor verifizieren            
   $b0  |Sektor suchen                  
   $c0  |Kopfanschlag                   
   $d0  |Programm im Puffer ausführen   
   $e0  |Programm im Puffer ausführen,  
        |vorher Laufwerksmotor ein-     
        |schalten und Kopf positionieren
--------+-------------------------------
 Was  man  mit  den  Job-Codes anfangen,
wollen  wir  anhand  von  einem Beispiel
zeigen.                                 
 Das  nachfolgende  Floppyprogramm  soll
Sektor $00 von Track $12 in den Buffer 0
laden.                                  
FLOPPYCODE: lda #$12     ;Tracknummer   
            sta $06      ;übergeben)    
            lda #$00     ;Sektornummer  
            sta $07      ;übergeben)    
            lda #$80     ;Jobcode lesen 
            sta $00      ;in Jobspeicher
EndSignal:  lda $00      ;Rückmeldung   
            bmi EndSignal;abwarten)     
            rts                         
 Dieses  Programm  muß natürlich erst in
die Floppy transportiert werden,damit es
ausgeführt  werden  kann.  Diese Aufgabe
erledigt unser nächstes Programm.       
       lda #$01  ;FLOOPY INITIALISIEREN 
       ldx #$08                         
       ldy #$6f                         
       jsr $fe00 (Filparmeter übergeben)
       lda #$00                         
       jsr $fdf9 (Filename=0)           
       jsr $f34a (Open)                 
       lda #$08                         
       jsr $ed0c (Listen)               
       lda #$6f                         
       jsr $edb9 (Seclst)               
       lda #"I"                         
       jsr $eddd (Init Floppy)          
       lda #$08                         
       jsr $edfe (Unlisten)             
**************************************  
       lda #$08  ;FCODE IN FBUFFER      
       jsr $ed0c (Listen)               
       lda #$6f                         
       jsr $edb9 (Seclst)               
       lda #"M"                         
       jsr $eddd                        
       lda #"-"                         
       jsr $eddd                        
       lda #"W"                         
       jsr $eddd                        
       lda #$00  ;ADRESSE LO            
       jsr $eddd                        
       lda #$05  ;ADRESSE HI            
       jsr $eddd                        
       lda #$11  ;$11 Bytes kpieren     
       jsr $eddd (m-w,nach $0500        
       ldy #$00                         
m01    lda FCODE,y                      
       jsr $eddd                        
       iny                              
       cpy #$11                         
       bne $m01 (Floppyrout.in def. Puff
       lda #$08                         
       jsr $edfe (Unlisten)             
;***************************************
       lda #$08                         
       jsr $ed0c (Listen)               
       lda #$6f                         
       jsr $edb9 (Seclst)               
       lda #"M"                         
       jsr $eddd                        
       lda #"-"                         
       jsr $eddd                        
       lda #"E"                         
       jsr $eddd                        
       lda #$00  ;STARTADRESSE LO       
       jsr $eddd                        
       lda #$05  ;SRARTADRESSE HI       
       jsr $eddd (m-e,start $0500)      
       lda #$08                         
       jsr $edfe (Unlisten)             
;***************************************
       lda #$08                         
       jsr $ed0c (Listen)               
       lda #$6f                         
       jsr $edb9 (Seclst)               
       lda #"M"                         
       jsr $eddd                        
       lda #"-"                         
       jsr $eddd                        
       lda #"R"                         
       jsr $eddd                        
       lda #$00  ;BUFFER ADRESSE        
       jsr $eddd                        
       lda #$03  ;BUFFER ADRESSE        
       jsr $eddd                        
       lda #$00  ;$00 = $0100           
       jsr $eddd (M-R,nach$0300         
       lda #$08                         
       jsr $edfe (Unlisten)             
       lda #$08                         
       jsr $ed09 (Talk)                 
       lda #$6f                         
       jsr $edc7 (Sectlk)               
       ldy #$00                         
m02    jsr $ee13                        
       sta $0400,y                      
       iny                              
       bne $m02 (Sektor a.Screen ausgebe
       lda #$08                         
       jsr $edef (Untalk)               
       lda #$01                         
       jsr $f291 (Close)                
       rts                              
FCode: lda #$12                         
       sta $06                          
       lda #$00                         
       sta $07                          
       lda #$80                         
       sta $00                          
m03:   lda $00                          
       bmi $m03                         
       rts                              
 Was noch zu beachten wäre,  ist daß Sie
immer nur $20 Hex-Bytes mit einem Schlag
in die Floppy übertragen können. Ist ihr
Floppyprogramm also länger,müssen sie es
schrittweise hineinschreiben.           
 Der Buffer für den Programmcode und der
Buffer für die Daten, dürfen nie  gleich
sein, weil der Programmcode  sich wärend
der  Ausführung  selbst  überschreiben  
würde.  Die  Folge  wäre ein Absturz der
Floppy.                                 
 Um die  Routine nun noch besser zu ver-
stehen, erkläre ich Ihnen kurz noch ein-
mal wie ich vorgegangen bin.            
1. initialisieren der Floppy.           
2. in Puffer 2 ($0500),wird die Floppy- 
   routine zum Lesen eines Blocks       
   geschrieben.                         
3. Start des Progamms in der Floppy.    
4. Einlesen des Blocks in P.0 ($0300).  
   Von dort aus abholen und auf dem     
   Bildschirm ausgeben.                 
Sie werden sich sicherlich gefragt haben
warum ich beim M-R  $00  als  Anzahl der
zu lesenden  Bytes angegeben habe.  Weil
die Angabe null Bytes zu lesen praktisch
gesehen einen sinnlose Aufgabe ist, wird
der Wert $00 intern in $100 umgewandelt.
Es  werden  also  $0100  Bytes  aus  dem
Floppybuffer geladen.                   
Da mit diesem Beispiel die Grundstein zu
Job-Code  Programmierung  gelegt  wurde,
dürfte auch der Direktzugriff in Assemb-
ler für Sie kein Problem mehr darstellen
Mit diesen Grundlagen müßten Sie eigent-
lich auch mit den anderen Job-Codes  zu-
recht kommen.                           
 Beim  Tüfteln  wünsche  ich  Ihnen viel
Spass  und  verabschiede  mich  bis  zum
nächsten Mal!                       (FB)
             Floppy Intern              
               (Teil IV)                
 Ich heisse   Sie herzlich Willkommen zu
4.Teil unseres Floppykurses.            
 Beginnen möchte ich mit den wichtigsten
Adressen,die die Floppy-Zeropage bietet.
Ich werde im  folgenden nur einige Zero-
pageadressen erklären,  da es einfach zu
aufwendig wäre, alle darzustellen.      
 Ich  verweise  Sie  jedoch auf das Buch
'Floppy Intern',  in  dem  die komplette
Zeropage beschrieben steht.  Dieses Buch
ist normalerweise  in  guten  Büchereien
zu haben.                               
Doch hier nun die wichtigsten Adressen: 
Adresse: Bedeutung:                     
$0000    Jobspeicher für Puffer 0       
$0001    "           "    "      1      
$0002    "           "    "      2      
$0003    "           "    "      3      
$0004    "           "    "      4      
$0005    "           "    "      5      
$0006/7  T+S fuer Befehl in Puffer 0    
$0008/9  "   "    "      "  "      1    
$000a/b  "   "    "      "  "      2    
$000c/d  "   "    "      "  "      3    
$000e/f  "   "    "      "  "      4    
$0010/11 "   "    "      "  "      5    
$0012/13 ID der Disk im ASCII-Format    
$0016-1a Daten im aktuellen Blockheader 
$0016    1.Zeichen der ID               
$0017    2.Zeichen der ID               
$0018    Tracknummer des Blocks         
$0019    Sektornummer des Blocks        
$001a    Pruefsumme des Blockheaders    
$001c    Flag f. Schreibschutz auf Disk 
Soviel zu den Zeropageadressen.         
        Das Aufzeichnungsverfahren      
        --------------------------      
 In  dem  folgenden Abschnitt wollen wir
uns damit befassen, wie die Bits von der
Floppyhardware  auf  die   Diskette  ge-
schrieben  und  von  dort wieder gelesen
werden.                                 
 Nachdem eine Diskette formatiert wurde,
ist sie in 35 Tracks unterteilt, die als
konzentrische Ringe angeordnet sind. Der
äußerste Track hat die Nummer 1 und     
der Innerste die Nummer 35.Zum Ansteuern
der  einzelnen Tracks  hat  das Laufwerk
einen  sog. Steppermotor,  mit  dem  der
Schreib/Lesekopf  über jeden Track posi-
tioniert werden kann.                   
Diese Tracks wiederum enthalten eine be-
stimmte Anzahl von Sektoren,die von Aus-
sen nach innen abnehmen,  da  auf  einen
äußeren Track  mehr  Sektoren passen als
auf einen Inneren.                      
Es stellt sich nun die Frage,wie man den
Anfang eines Sektors auf einem Track er-
kennt.  Man  müßte  also bestimmte Byte-
oder Bitkombinationen bevorzugt erkennen
können,  die als Daten-Bytes  nicht vor-
kommen können.  Mit 8 Bit ist es möglich
256 Bytekombinationen darzustellen,  die
aber jedoch auch  alle   Datenbytes sein
könnten.  Der Schlüssel zur Lösung liegt
darin,  ein Byte nicht durch 8,  sondern
für die Diskettenaufzeichnung durch mehr
Bits darzustellen. Dieses Verfahren wird
als "Group Code Recording"(GCR) bezeich-
net.                                    
 Jeder  Sektor  besteht aus einem BLOCK-
HEADER und dem dazugehörigen DATENBLOCK.
Sowohl  der  Block-Header  als  auch der
Datenblock besitzen zu Beginn eine SYNC-
Markierung.                             
 Stößt der der Schreib/Lesekopf auf eine
solche SYNC-Markierung, dann muß sie nur
noch  feststellen  ob  es  sich um einen
Blockheader oder Datenblock handelt.    
 Unterschieden werden sie durch das Byte
das sich gleich hinter Markierung befin-
det.Den Blockheader erkennt man an einem
$08 und den Datenblock an einem $07 Byte
Danach folgt noch die  Prüfsumme die zur
Lesefehlerkontrolle dient.  Die nachfol-
gende  Tabelle  zeigt  den  Aufbau eines
Headders und eines Datenblocks.         
****************************************
* Sync                         *       *
* $08                          *   H   *
* Pruefsumme                   *   e   *
* aktueller Sektor             *   a   *
* aktueller Track              *   d   *
* ID1                          *   e   *
* ID2                          *   r   *
* Luecke                       *       *
*                              *       *
****************************************
****************************************
*                              *   D   *
* Sync                         *   a   *
* $07                          *   t   *
* Track                        *   e   *
* Sektor                       *   n   *
* 254 Byte Daten               *   b   *
* Pruefsumme                   *   l   *
* Luecke                       *   o   *
*                              *   c   *
*                              *   k   *
****************************************
Nachdem sie sich nun mit dem grundlegen-
dem Aufbau der Diskette vertraut gemacht
haben,  möchte  ich  etwas näher auf die
Synchronmarkierungen eingehen.          
Wie wir schon wissen, bestehen die Syncs
aus 5 $ff Bytes.  Stellen  Sie  sich nun
vor,  man hätte einen Block voll mit $ff
Bytes. Die  Floppy  könnte die Syncs von
den  Datenbytes nicht mehr unterscheiden
und  das   Ergebnis  wäre  eine  totales
Chaos  bei  der  Datenorganisation.  Aus
diesem  Grund  haben sich die Entwickler
der Floppystation die GCR-Codierung ein-
fallen lassen.                          
  Damit die Zusammenhaenge verstaendlich
werden  möchte  ich kurz auf die Technik
eingehen,  die  beim Lesen von Bytes ge-
schieht.                                
 Der  Diskcontroller besitzt einen Timer
der  in  bestimmten  Zeitabständen fest-
stellt,  ob  ein  Magnetisierungswechsel
stattgefunden hat.                      
  Bei gleichbleibender Richtung wird ein
0-Bit,bei veränderter Richtung ein 1-Bit
dargestellt.                            
 Wenn also ein Byte von der Diskette ge-
lesen werden soll,  so  wartet der Disk-
controller eine bestimmte  Zeit  die zum
Lesen von 8-Bit erforderlich ist.       
 Leider  kann ein Laufwerk nicht absolut
gleichmässig   gedreht   werden, deshalb
wird  es  notwendig  nach jedem Magneti-
-sierungswechsel  den  Timer  neu einzu-
-stellen, um Lesefehler zu vermeiden.   
 Logischerweise  darf es also nicht pas-
sieren  das zu viele $00 Bytes hinterei-
nander folgen,  da  sonst zu lange keine
Laufwerkskontrolle   mehr   durchgeführt
wird.                                   
Natürlich sind auch zu viele 1-Bit nicht
gestattet, so sonst ein Sync-Signal aus-
gelöst werden würde.  Deshalb müssen die
Daten,bevor sie auf Diskette geschrieben
werden, GCR-Codiert werden.             
Durch diese Technik wird ausgeschlossen,
daß  zu  viele  0-Bit  und  1-Bit direkt
hintereinander   folgen  und  somit  die
Schreib- und Leseelektronik stören.     
Lediglich  Sync-Markierungen,  also mehr
als 8 1-Bit,  werden  vom  DOS uncodiert
auf die  Diskette  geschrieben.  Es gibt
also zwei Schreibarten:                 
1.Schreiben von Syncs                   
Es werden 5 $ff Bytes hintereinander ge-
schrieben, die der Orientierung dient.  
2.Schreiben von Daten                   
Hier werden die Byte-Inhalte codiert, da
sie von den Syncs unterschieden   werden
müssen.  Hier nun die Umrechnungstabelle
für die Binär-GCR Umwandlung:           
Hexadezimal:  Binaer:  GCR:             
    $0        0000     01010            
    $1        0001     01011            
    $2        0010     10010            
    $3        0011     10011            
    $4        0100     01110            
    $5        0101     01111            
    $6        0110     10110            
    $7        0111     10111            
    $8        1000     01001            
    $9        1001     11001            
    $a        1010     11010            
    $b        1011     11011            
    $c        1100     01101            
    $d        1101     11101            
    $e        1110     11110            
    $f        1111     10101            
Wie sich erkennen laesst,handelt es sich
bei der  GCR-Codierung  um  einen  5-Bit
Code. Jedes 4-Bit Nibble das umgewandelt
wird, wird praktisch zu einem 5-Bit GCR-
Nibble,  d.h. ein  Byte  was  vorher aus
8-Bit bestand,  wird durch die Codierung
zu 10-Bit.                              
Beim GCR-Codieren werden deshalb jeweils
immer 4 Byte gleichzeitig umgewandelt.  
Als  Ergebnis erhält man dann logischer-
weise 5 Byte.                           
 Durch  diese Technik erhält man für den
Diskcontroller ungefährliche Werte.  Zum
Schluss  fehlt  eigentlich  nur noch die
Prüfsumme,   die ebenfalls zur Erkennung
von eventuellen Fehlern bestimmt ist.   
 Hier  nun die Berechnung der Prüfsumme:
Es werden alle Bytes des Programms  add-
iert und zum  Ergebnis  noch 2 Bytes der
Startadresse hinzugezählt.  Dieses Erge-
bnis besteht aus einem  Low -und Hibyte.
  Das Lowbyte ist die Prüfsumme,  zu der
noch  der  Übertrag  im  Hibyte  addiert
werden muß.  Das  Endergebnis  muß immer
kleiner als 256 sein. Damit sind wir mal
wieder am Ende des Kursteils angelangt. 
Nachdem wir uns nun hervorragend mit dem
Aufbau  und  der  grundlegenden Technik,
die  sich  dahinter  verbirgt,   bestens
auskennen,  möchte  ich  ab dem nächsten
Teil  mit  dem Entwickeln von nützlichen
Utilities beginnen.                     
                    Bis dahin,          
                      Ihr Frank Boldewin
            Floppy Intern               
            -------------               
 Ich  heisse Sie herzlich willkommen zum
5.Teil unseres Floppykurses.            
 Da in den letzten 4 Teilen die Routinen
etwas zu kurz gekommen sind,  möchte ich
Ihnen  diesmal  folgende  Routinen  vor-
stellen:                                
1.Whole-Load + Whole-Save               
  Diese beiden Files ermöglichen es auch
den  Bereich  ab  $d000  zu laden und zu
speichern!                              
2.Directory                             
  Dieses File beschreibt eine Directory-
routine,  die  beim  Lesen der BAM nicht
den Bereich ab $0800 zerstört!          
3.Read 41 + Write 41                    
Diese beiden Files beinhalten eine Lese-
und schreibe Routine fuer den Track 41! 
Diese  Files  befinden  sich  auf  ihrer
Diskette und können mit  $CD00 gestartet
werden.                                 
  Beginnen möchte nun ich mit der Whole-
Load Routine.                           
 Wie Sie als Assemblerprogrammierer sehr
wahrlich  wissen  läßt  sich  auch   der
Bereich :$a000-$c000                    
         $d000-$ffff                    
nutzen,  indem man in die Speicherstelle
$01 Werte zwischen $34 und $37 poked.   
Wie  aber  läßt sich der Bereich abspei-
chern?                                  
 Von Modulen wie  z.B. die Action Replay
wissen wir, daß dies ohne weiteres funk-
tioniert.                               
  Was aber ist wenn Sie zum Beispiel ein
Spiel geschrieben haben  mit  Highscore-
Save und Sie nur noch einen  Bereich bei
$d000 frei haben?                       
 Die normale Systemroutine zum laden und
Speichern  von  Files  funktioniert hier
nicht  und auch Ihr Modul kann Ihnen bei
diesem Problem nicht helfen!            
Ich stelle Ihnen nun zuerst eine Routine
zum  laden  eines  Files  ab  $d000  vor
und  danach  die  dazugehörige Speicher-
routine.                                
    lda #$01   ;Filenummer              
    ldx #$08   ;Geraetenummer           
    ldy #$00   ;Sekundaeradresse        
    jsr $fe00  ;setzen                  
    lda #$     ;laenge Filename         
    ldx #$     ;Lo- und                 
    ldy #$     ;Hi-Byte Filename        
    jsr $fdf9  ;setzen                  
    jsr $f34a  ;open                    
    ldx #$01   ;geraet auf              
    jsr $f20e  ;Empfang schalten        
    jsr $ee13  ;startadresse            
    sta $ae    ;des                     
    jsr $ee13  ;Files                   
    sta $af    ;holen                   
m02 jsr $ee13  ;1 Byte lesen            
    sei        ;IRQ setzen              
    ldy #$00   ;Zaehler auf null        
    ldx #$34   ;kompletten              
    stx $01    ;Speicher freigeben      
    sta ($ae),y ;und abspeichern        
    ldx #$37   ;Urzustand               
    stx $01    ;wieder herstellen       
    cli        ;IRQ loeschen            
    inc $ae    ;Zaehler erhoehen        
    bne $m01   ;schon Null?             
m01 inc $af    ;dann naechster Block    
    bit $90    ;Ende des Files schon    
    bvc $m02   ;erreicht,sonst weiter   
    jsr $f333  ;Empfang aus             
    lda #$01   ;Close                   
    jmp $f291  ;File                    
 Wie Sie sehen, bestand der Trick darin,
daß  wir  das File byteweise reingeladen
und vor dem Poke in den Speicher einfach
den Vektor $01 verändert haben.         
 Somit  stand uns der komplette Speicher
zur Verfügung.                          
 Das  dieser  Trick  auch beim Speichern
funktioniert versteht sich von selbst.  
Hier nun die Speicherroutine:           
    lda #$01   ;Filenummer              
    ldx #$08   ;Geraetenummer           
    ldy #$00   ;Sekundaeradresse        
    jsr $fe00  ;setzen                  
    lda #$     ;laenge Filename         
    ldx #$     ;Lo- und                 
    ldy #$     ;Hi-Byte Filename        
    jsr $fdf9  ;setzen                  
    lda #$61   ;Kanal 1+$60 fuer Save in
    sta $b9    ;Sekundaeradresse poken  
    jsr $f3d5  ;IEC-Bus eroeffnen       
    lda #$08   ;Geraeteadresse          
    jsr $ed0c  ;Listen                  
    lda #$61   ;Sekundaeradresse        
    jsr $edb9  ;Seclst                  
    ldx #$     ;Lo- und                 
    ldy #$     ;Hi-Byte                 
    stx $ac    ;der                     
    sty $ad    ;Startadresse            
    ldx #$     ;Lo- und                 
    ldy #$     ;Hi-Byte                 
    stx $ae    ;der                     
    sty $af    ;Endadresse              
    lda $ac    ;Startadresse            
    jsr $eddd  ;ins                     
    lda $ad    ;File                    
    jsr $eddd ;schreiben                
m01 sei        ;IRQ setzen              
    ldy #$00   ;Zaehler=0 und kompletten
    sty $01    ;Speicher freigeben      
    lda ($ac),y ;Byte holen             
    ldy #$37   ;Urzustand wieder        
    sty $01    ;herstellen              
    cli        ;IRQ loeschen            
    jsr $eddd  ;und Speichern           
    jsr $fcdb  ;diese Routinen werden im
    jsr $fcd1  ;Anschluss hieran        
    bcc $m01   ;erklaert                
    jsr $edfe  ;Unlisten                
    lda #$08   ;Geraeteadresse          
    jsr $ed0c ;Listen                   
    lda #$e1   ;Sekundaeradresse + Bit 7
    jsr $edb9  ;Seclst                  
    jmp $edfe  ;Unlisten                
In dieser Routine haben wir nun zwei Un-
bekannte. Zunächst mal die Kombination: 
        lda #$61                        
        sta $b9                         
        jsr $f3d5                       
        lda #$08                        
        jsr $ed0c                       
        lda #$61                        
        jsr $edb9                       
 Diese  Routine ist eine andere Form der
'Open'  Routine  und dient lediglich der
neuen Erkenntnis!                       
Dann waren im Code noch 2 Systemadressen
die ich angesprungen habe.              
        jsr $fcdb                       
       +jsr $fcd1                       
In $fcdb steht folgende Routine:        
        inc $ac                         
        bne $m01                        
        inc $ad                         
    m01 rts                             
 Hier werden  eigentlich nur die Counter
für den Speicherbereich erhöht.         
In $fcd1 steht dann:                    
        sec                             
        lda$ac                          
        sbc$ae                          
        lda$ad                          
        sbc$af                          
        rts                             
  Hier werden die noch verbleibenden von
den schon geschriebenen Bytes abgezogen.
 Damit  die  Routine so kurz wie möglich
bleibt,  habe  ich  diese beiden System-
routinen angesprungen!                  
Das File WholeSave speichert den Bereich
von $d000-$e000 ab und kann mit dem File
WholeLoad wieder reingeladen werden.    
  Das File das abgespeichert und geladen
werden kann habe ich 'TEST' genannt!    
 Nachdem  wir  nun  über  das  Laden und
Speichern  von  Files  bestens  bescheid
wuessen,  möchte  ich  Sie nun mit einer
neuen   nützlichen   Routine    vertraut
machen, der Directory Routine!          
  Vor allem deshalb nützlich, weil diese
Routine  bei  einer  längeren  Directory
nicht in den eventuellen Programmbereich
ab $0800 reinschreibt!                  
 Denn ich denke, jedem  ist es schon mal
passiert, der gerade ein tolles Programm
geschrieben  hat  und jetzt gerne wissen
moechte,ob noch genug Platz auf der Disk
ist.                                    
 Die  Directory  wird geladen, zufrieden
stellt man fest:                        
 Es ist ja noch genug Platz frei!       
Als  nun  der letzte  Blick auf das Pro-
gramm erfolgt,  muß man voller Wut fest-
stellen,  daß  die  Directory,  das neue
Programm  zum  Teil  überschrieben  hat.
C-64  Besitzer  die  von  Beginn  an ein
Modul  besessen  haben,  werden   dieses
Dilemma nie erlebt haben,  da eigentlich
alle  Module  eine Directory Routine be-
nutzen, die nicht in den Programmbereich
ab $0800 schreibt.                      
 Die Routine  die  ich  Ihnen jetzt vor-
stelle,  verhindert nicht nur,   daß ein
Programm  überschrieben  wird,   sondern
ist  auch  schneller  und kürzer als die
System Routine!                         
    ldx #$08  ;Geraeteadresse;          
    ldy #$00  ;Sekundaeradresse;        
    jsr $fe00 ;setzen;                  
    lda #$01  ;1 Byte ab;               
    ldx #$60  ;$a360='$' fuer;          
    ldy #$a3  ;BAM Zugriff;             
    jsr $fdf9 ;setzen;                  
    jsr$f34a open;                      
    ldx#$01  Eingabegeraet;             
    jsr$f20e setzen;                    
    jsr$f157 Header holen;              
    jsr$f157 mit BASIN;                 
m03 jsr$f157 Track + Sektor;            
    jsr$f157 holen mit BASIN;           
    lda$90   Status-Bit;                
    bne$m01  testen;                    
    jsr$f157 in A/X 16-Bit;             
    tax      Blockzahl;                 
    jsr$f157 holen und in;              
    jsr$bdcd Dezimal umrechnen;         
    jsr$ab3b Space;                     
m02 jsr$f157 1 Byte vom Filename;       
    jsr$f1ca holen und ausgeben;        
    bne$m02  Schon alle Bytes?;         
    lda#$0d  dann ASCII $0d fuer;       
    jsr$f1ca Return ausgeben;           
    lda$dc01 Komplette;                 
    cmp#$7f  Directory schon;           
    bne$m03  ausgegeben?;               
m01 lda#$01  dann;                      
    jsr$f291 Close;                     
    jmp$f333 aktiven Kanal schliessen;  
 Wie  Sie  sehen  ist  diese Routine gar
nicht so schwer zu verstehen.           
Lediglich  zwei  neue   System  Routinen
habe ich benutzt!                       
1. jsr $bdcd                            
 Diese Routine wandelt eine Hexadezimale
Zahl in eine Dezimale Zahl um.          
 Vorher muß man nur in die Register Akku
und X Hi-und Lo-Byte der Hexzahl eintra-
gen.                                    
2. jsr $ab3b                            
Diese Systemroutine gibt ein Leerzeichen
auf  dem  Bildschirm aus, denn  zwischen
Blockzahl  und  Filename  ist stets eine
Leerstelle.                             
               Kopierschutz             
               ------------             
 Das letzte Thema, mit dem wir uns heute
befassen  werden  ist wohl eines der um-
strittensten in der C-64 Geschichte. Ich
spreche vom altbekannten Kopierschutz!  
 In den Jahren  1985-1988 lieferten sich
Softwarehaeuser  und  Raubkopierer   ein
packendes Duell!                        
 Die  Softwarefirmen  steckten sehr viel
Zeit  und  Geld  in  ihre Kopierschütze!
Die  Raubkopierer  entwicklelten  unter-
dessen  nach  jeder  neuen Kopierschutz-
variante ein neues Kopierprogramm!  Hier
ein paar Varianten von Kopier-          
schuetzen:                              
1.Halftracks                            
(der Kopf wird nur um einen halben Track
bewegt)                                 
2.Speedchange                           
(die Bitrate wurde auf eine andere      
Geschwindigkeit eingestellt)            
3.Readerrors                            
(absichtliches erzeugen eines Fehlers)  
4.Format 41                             
(eine Diskette wird statt 35 Tracks auf 
41 Tracks formatiert.)                  
 Vom  Floppy-DOS  aus  sind dieses alles
Fehler,  die  nicht  verarbeitet  werden
koennen, folglich  beim  kopieren  nicht
beruecksichtigt werden.                 
  Die Kopie enthält also den absichtlich
erzeugten Fehler nicht mehr.            
Hier genau ist der Trick eines Schutzes!
Denn fragte man diesen  Fehler  im Spiel
ab und er war nicht mehr vorhanden,waren
auf  einmal  entweder keine Sprites mehr
zu sehen oder das Spiel hing sich völlig
auf!                                    
 Der  schlaue  User  kaufte sich deshalb
lieber  ein  Original  um es auch 100%ig
Fehlerfrei spielen zu können!           
 Nicht aber die Raubkopierer, die sofort
versuchten  ein  besseres Kopierprogramm
zu schreiben,dass auch den neuen  Schutz
kopierte!                               
Hiermit  war  das  Programm zwar kopiert
und  100%ig  lauffähig,  nicht  aber der
Schutz entfernt!                        
 Später  fingen  dann ein paar Freaks an
das  Programm  nicht  nur  zu  kopieren,
sondern auch  die Schutzabfrage zu über-
gehen,  so daß das Spiel von jedem X-be-
liebigen  Kopierprogramm  kopiert werden
konnte.                                 
 Es gab fortan also zwei Arten von Soft-
warefirmengegnern:                      
1.Die Raubkopierer -sie waren noch recht
  harmlos für die Firmen,  da nur wenige
  so gute Kopierprogramme besassen.     
2.Die Cracker-sie waren die eigentlichen
  Firmenschaedlinge, da  sie  den Schutz
  komplett  entfernten  und jeder es ko-
  pieren konnte.                        
Soviel zur Geschichte!                  
 Ich  stelle  Ihnen  jetzt  einen Schutz
aus  dem  oben  genannten Sortiment vor.
Ich spreche vom  Format 41 Schutz!   Wie
schon erwähnt,  muß  die Diskette vorher
mit einem Disketteneditor auf  41 Tracks
formatiert werden.                      
 Hier für eignet sich zum  Beispiel  der
Disk-Demon!                             
Nachdem nun die Diskette dementsprechend
formatiert wurde,  müssen  wir  zunächst
mal eine  Write-Routine für den Track 41
entwickeln.                             
 Auf der Diskette befindet sich das dazu
gehörige  Programm,  welches  auch   die
Floppyroutine in die Floppy verfrachtet.
 Da die  Routine  zum starten eines Pro-
gramms in der Floppy eigentlich aus  den
vergangenden   Kursteilen  bekannt  sein
müßte,  erkläre  ich  nun  lediglich die
Floppyroutine:                          
    lda#$03    Puffer ab                
    sta$31     $0300                    
    jsr$f5e9   Parity fuer Puffer       
    sta$3a     berechnen u. speichern   
    jsr$f78f   Puffer in GCR umrechnen  
    jsr$f510   Headerblock suchen       
    ldx#$09                             
m01 bvc$m01    Byte ready?              
    clv                                 
    dex        9 Bytes GAP nach Header- 
    bne$m01    block ueberlesen         
    lda#$ff    Port A (Read/Writehead)  
    sta$1c03   auf Ausgang              
    lda$1c0c   PCR auf                  
    and#$1f    Ausgabe                  
    ora#$c0    umschalten               
    sta$1c0c   CB2 lo                   
    lda#$ff    Sync                     
    ldx#$05    5x                       
    sta$1c01   auf die                  
    clv        Diskette schreiben       
m02 bvc$m02    Byte ready?              
    clv                                 
    dex                                 
    bne$m02                             
    ldy#$bb    Bytes $01bb bis $01ff    
m04 lda$0100,y =69 GCR Bytes            
m03 bvc$m03    auf die                  
    clv        Diskette                 
    sta$1c01   schreiben                
    iny                                 
    bne$m04                             
m06 lda($30),y Datenpuffer 256 Bytes    
m05 bvc$m05    GCR-Code auf die         
    clv        Diskette schreiben       
    sta$1c01                            
    iny                                 
    bne$m06                             
m07 bvc$m07    Byte ready?              
    lda$1c0c   PCR wieder               
    ora#$e0    auf Eingabe umschalten   
    sta$1c0c   CB2 hi                   
    lda#$00    Port A (Read/Writehead)  
    sta$1c03   auf Eingang              
    jsr$f5f2   GCR in Normalcode wandeln
    lda#$01    Ok                       
    jmp$f969   Meldung!                 
Start der Floppy Routine:               
      ldx#$09    10 Bytes               
m08   lda text,x Text in                
      sta$0300,x Writepuffer            
      dex        ab $0300               
      bpl$m08    poken                  
      ldx#$29    Track 41               
      ldy#$00    Sektor 0               
      stx$0a     abspeichern            
      sty$0b     und                    
      lda#$e0    Programm               
      sta$02     ab $0500               
m09   lda$02     starten                
      bmi$m09    und ausfuehren         
      rts        Ende                   
text. "protect41!"                      
 Sehen  wir  uns  nun  zunächst  mal den
Start der Floppyroutine an.             
Hier wird ein Programm durch Jobcode $E0
ab  $0500  gestartet um einen Text,  der
nach $0300 geschoben wurde, auf die Disk
zu schreiben (auf Track 41,Sektor 0).   
Gehen  wir  nun  noch  mal  die Schritte
zum schreiben  eines Blocks auf Diskette
durch:                                  
A.Write Puffer angeben ($31)            
B.Paritaet berechnen   ($f5e9)          
C.Normalcode in GCRcode wandeln ($f78f) 
D.Headerblock suchen ($f510)            
E.9 Bytes GAP nach dem Headerblock      
  ueberlesen (Warteschleife)            
F.Port A auf Ausgang ($1c03)            
G.PCR auf Ausgabe umschalten ($1c0c)    
H.5 Syncs (#$ff) auf Diskette schreiben 
I.durch die GCR Umwandlung wurden aus   
  256,325 Bytes (siehe Kurs 4),also     
  69 Bytes mehr im Ausweichpuffer von   
  $01bb-$01ff zuerst geschrieben werden.
J.dann folgen die restlichen 256 Bytes  
  die von $0300 - $03ff stehen.         
  Die Adresse zum Lesen und Schreiben   
  von Bytes ist ($1c01).                
K.PCR auf Eingabe umschalten ($1c0c)    
L.Port A auf Eingang ($1c03)            
M.GCRcode in Normalcode wandeln ($f5f2) 
N.Programm beenden mit ($f969)          
Unsere  Installationsroutine  wäre damit
beendet!                                
 Sehen  uns  nun als nächstes  die Lese-
routine bzw. die Schutzabfrage an.      
    lda#$03     Puffer                  
    sta$31      ab $0300                
    jsr$f50a    Datenblockanfang suchen 
m01 bvc$m01     Byte ready?             
    clv                                 
m03 lda$1c01    Datenbyte holen         
    sta($30),y  und 256 mal             
    iny         in Puffer               
    bne$m01     schreiben               
    ldy#$ba                             
m02 bvc$m02     Byte ready?             
    clv                                 
    lda $1c01   Datenbyte holen         
    sta $0100,y und 69 mal              
    iny         nach $01ba - $01ff      
    bne $m02    schreiben               
    jsr $f8e0   Daten aus GCR berechnen 
    ldx #$00    Text mit                
m04 lda text,x  gelesenen               
    cmp $0300,x Daten vergleichen       
    bne $m03    nicht gleich?           
    inx         sonst                   
    cpx #$0a    noch ein Byte vergleiche
    bne $m04    bis alle verglichen     
    lda #$01    ok                      
    jmp $f969   Meldung!                
text. "protect41!"                      
Start der Floppyroutine:                
    ldx #$29   Track 41                 
    ldy #$00   Sektor 0                 
    stx $0a    poken                    
    sty $0b    und                      
    lda #$e0   Programm                 
    sta $02    bei $0500                
m05 lda $02    starten und              
    bmi $m05   ausführen                
    rts        Ende                     
 Gehen  wir  nun  wieder  die  einzelnen
Schritte durch:                         
1.Readpuffer ab $0300 ($30+$31)         
2.Datenblockanfang suchen ($f50a)       
3.256 Bytes nach $0300 holen und die    
  restlichen Bytes nach $01ba - $01ff   
  mit Adresse ($1c01) werden Bytes von  
  der Diskette abgeholt.                
4.GCRcode in Normalcode wandeln ($f8e0) 
5.Abfrage ob richtiger Text im Speicher,
  wenn nein=Absturz der Floppy          
  wenn ja  =ok Meldung ($f969)          
 Bevor sie die Routinen starten, sollten
sie  die  Floppy  stets  zuerst  Reseten
und Initialisieren, da sonst unbeabsich-
tigt   falsche   Daten   gelesen  werden
könnten.                                
 Sicherlich ist die Abfrage in der Lese-
routine  leicht  zu finden und  zu über-
gehen, für den geübten Cracker! Doch ich
denke  das  Grundprinzip  eines  Kopier-
schutzes  ist  erklärt  und Ihnen stehen
nun  die  Türen  offen  einen  besseren,
schwerer zu  analysierenden Kopierschutz
zu entwickeln.                          
 Ebenfalls  haben  sie  leichtveränderte
Routinen kennengelernt, die  das  System
für  die  Jobcodes, $80-lesen  und   $90
schreiben, benutzt.                     
Beim naechsten Mal beschaeftigen wir uns
dann  mit d er Speederprogrammierung und
schliessen damit auch  gleichzeitig  un-
sere Floppykursreihe ab!                
Bis dahin,                              
          Frank Boldewin                
           Floppy Intern                
           -------------                
              (Teil 6)                  
Herzlich willkommen zum letzten Teil un-
seres Floppykurses.                     
 Nach harter Vorarbeit,  ist  es endlich
soweit,sich als letzte Hürde den Floppy-
speeder zu setzen.Dies ist ein Programm,
welches es dem User ermöglich Daten  mit
vielfacher Geschwindigkeit zu laden.    
 Ich werde dazu zunächst den Vorgang der
seriellen  Programmierung  erklären, was
mit  Hilfe  von bestimmten Registern ge-
schiet.                                 
 Danach  werden  wir  genaustens auf den
"Floppyspeeder" eigehen,  der  sich  als
Objectcode auf Seite 1 dieser Magic Disk
befindet.                               
 Zunächst  die  Tabelle über die CIA Zu-
stände.                                 
C64:   Bit: Signal: Richtung: 1541: Bit:
----------------------------------------
$dd00  3    ATN       =>      $1800 7   
----------------------------------------
$dd00  5    DATA      =>      $1800 0   
$dd00  7              <=      $1800 1   
----------------------------------------
$d000  4    CLK       =>      $1800 2   
$dd00  6              <=      $1800 3   
----------------------------------------
  Bei der Übertragung von Bytes wird zu-
zunächst die ATN (Attention) Leitung auf
High geschaltet.Im C64 müssen zusätzlich
noch  Bit  0+1  auf  1  und  Bit 2 auf 0
stehen. Daraus ergibt sich also der Wert
11=$0b,  der in $dd00 geschrieben werden
muß,  um dem C64 mitzuteilen, daß gleich
Daten folgen.                           
 Im C64 gibt es nur eine ATN-Leitung die
Ein -und Ausgang steuert.               
 In  der  Floppy  hingegen ist Bit 4 für
den Ausgang und  Bit 7  für  den Eingang
des ATN Signals verantwortlich.         
 Da Daten von der Floppy zum C64 fließen
müssen  wir  also  Bit 4  (Ausgang)  auf
High schalten.                          
In Port $1800 steht demnach der Wert $10
Dadurch  weiß  die  Floppy,  daß  gleich
Daten herausgeschickt werden.           
 Wie  Sie vieleicht schon bemerkt haben,
lassen  sich  leider  keine ganzen Bytes
übertragen,   sondern jedes einzelne Bit
muß mühevoll durch die Leitung geschoben
werden.  Daß  dieser Vorgang lange Lade-
zeiten beschert,  brauche ich wohl nicht
näher zu erklären.                      
  Um nun die Daten sauber über die Data-
Leitung zu bekommen,  müssen  diese  auf
die Mikrosekunde genau getaktet werden. 
Dieser Vorgang geschieht durch die Clock
Leitung.   Hierdurch  erspart  man  sich
komplizierte Zyklenausgleiche.          
 Ohne  diese  Leitung  wäre beim zweiten
Bit die Übertragung beendet,  da der VIC
die  Arbeit  des  C64  regelmäßig für 40
Zyklen  unterbricht,  um  den Bildschirm
aufzufrischen.                          
 Dadurch  würden C64 und 1541 nicht mehr
synchron  arbeiten  und  die Chance, die
gewünschten  Daten  zu  bekommen, dahin.
Um den  Bildschirmaufbau  zu verhindern,
schreibt  man  einfach  eine 0 in $d011.
Danach sperrt man noch  schnell  den IRQ
mit SEI.                                
Durch diesen Trick ist die Clock-Leitung
frei  geworden  und  sie kann zusätzlich
zur Übertragung genutzt werden.         
 Das Timing zwischen C64 und 1541 bleibt
nun uns selbst überlassen.              
Gesagt sei noch,   daß in der Floppy die
Bits 1+3 (Data+Clock Ausgang) und im C64
die  Bits 6+7  (Data+Clock Eingang)  den
Datenverkehr regeln.                    
Im folgenden werde ich die  C64 und 1541
Routine  zur Übertragung eines Bytes er-
klären.                                 
1541 Routine: (Beispiel Byte $EA)       
    lda   #$ea  ;Byte                   
    sta   $c1   ;merken                 
m01 lda   $1800 ;auf Attention          
    bpl   m01   ;warten                 
    lda   #$10  ;Data                   
    sta   $1800 ;setzen                 
m02 lda   $1800 ;auf C64                
    bmi   m02   ;warten                 
    lda   #$00                          
    rol   $c1                           
    rol                                 
    rol                                 
    rol   $c1                           
    rol                                 
    rol                                 
    sta   $1800 ;Bits 5 und 7           
    lda   #$00                          
    rol   $c1                           
    rol                                 
    rol                                 
    rol   $c1                           
    rol                                 
    rol                                 
    sta   $1800 ;Bits 4 und 6           
    lda   #$00                          
    rol   $c1                           
    rol                                 
    rol                                 
    rol   $c1                           
    rol                                 
    rol                                 
    sta   $1800 ;Bits 1 und 3           
    lda   #$00                          
    rol   $c1                           
    rol                                 
    rol                                 
    rol   $c1                           
    rol                                 
    rol                                 
    sta   $1800 ;Bits 0 und 2 übertragen
    nop         ;durch                  
    nop         ;6 Taktzyklen           
    nop         ;ausgleichen            
    lda   #$0f  ;ATN                    
    sta   $1800 ;zurücksetzen           
    rts         ;Ende                   
Wie Sie vieleicht bemerkt haben, muß man
diese Routine sehr sorgfältig entwickeln
da die  Clock Leitung ihrer eigentlichen
Aufgabe  entmächtigt  wurde  und nun als
zusätzliches Übertragungsbit dient.     
Auch bei der C64 Routine ist der Zyklen-
ausgleich  nötig  wie  Sie  gleich sehen
werden.                                 
    lda  #$0b   ;ATN                    
    sta  $dd00  ;setzen                 
m01 lda  $dd00  ;auf Data Leitung       
    bpl  m01    ;warten                 
    lda  #$03   ;ATN                    
    sta  $dd00  ;zurücksetzen           
    inc  $d020  ;mit                    
    jsr  m02    ;30                     
    nop         ;Takt-                  
    nop         ;zyklen                 
    nop         ;aus-                   
    dec  $d020  ;gleichen               
    lda  $dd00                          
    rol                                 
    php                                 
    rol                                 
    rol  $08                            
    plp                                 
    rol  $08    ;Bits 5 und 7           
    lda  $dd00                          
    rol                                 
    php                                 
    rol                                 
    rol  $08                            
    plp                                 
    rol  $08    ;Bits 4 und 6           
    lda  $dd00                          
    rol                                 
    php                                 
    rol                                 
    rol  $08                            
    plp                                 
    rol  $08    ;Bits 1 und 3           
    lda  $dd00                          
    rol                                 
    php                                 
    rol                                 
    rol  $08                            
    plp                                 
    rol  $08    ;Bits 0 und 2 übertragen
    lda  $08    ;Byte                   
    eor  #$ff   ;invertieren            
m02 rts         ;Ende                   
Sie werden sich vieleicht wundern, warum
zum  Schluss  der Routine der ganze Wert
invertiert wird.                        
Die Ursache liegt in der Hardware!   Die
Entwickler haben keine Inverter vor  die
Ein- und Ausgänge geschaltet, so daß je-
des  vollständig  übertragene  Bit soft-
waremässig invertiert werden muß.       
Diese  Routinen  sind  eigenständig  und
können in der 1541 bzw. im  C64  mit JSR
angesprungen werden.                    
Auf der Diskette befindet sich ein Fast-
loader,  der sich bei genauerem Betrach-
ten in 5 Teile aufteilen läßt.          
1.Eine Routine die das Floppyprogramm   
  in die 1541 verfrachtet.              
2.Eine Routine die sich das File vom    
  ersten bis zum letzten Byte in den    
  C64 Speicher holt.                    
3.Die eben beschriebene Routine zur     
  Uebertragung eines Bytes              
  (1541-Routine).                       
4.Und die eben beschriebene Routine zur 
  Uebertragung eines Bytes              
  (C64-Routine).                        
5.Eine Routine die sich das File in den 
  1541 Speicher holt.                   
 Die  Routinen  1 und 2  können  wir uns
getrost  sparen,  denn  solche  Routinen
wurden schon in früheren Kursteilen ent-
wickelt. Nummer 3 und 4 haben wir oben  
schon besprochen.                       
 Lediglich Routine 5 bedarf einer kurzen
Erlaeuterung.                           
    lda #$12    ;Zähler=0?              
    sta $1c07   ;nächster Stepperschritt
    lda #$03    ;aktueller              
    sta $31     ;Puffer 0 ($0300)       
    jsr $f50a   ;Datenblockanfang suchen
m01 bvc m01     ;Ready?                 
    clv         ;Flag loeschen          
    lda $1c01   ;1 Byte lesen           
    sta ($30),y ;und ab $0300 speichern 
    iny         ;Zaehler erhoehen       
    bne m01     ;Puffer schon voll?     
    ldy #$ba    ;Überlaufpuffer benutzen
m02 bvc m02     ;Ready?                 
    clv         ;Flag löschen           
    lda $1c01   ;1 Byte lesen           
    sta $0100,y ;und ab $01ba speichern 
    iny         ;Zähler erhoehen        
    bne m02     ;schon letztes Byte?    
    jsr $f8e0   ;GCR-Code umwandeln     
    rts         ;Ende                   
 Diese  Routine  macht eigentlich nichts
anderes als der Jobcode $80, der für das
Lesen von Sektoren verantwortlich ist.  
Ich habe diese Routine deshalb verwendet
weil ein Blick hinter die  Kulissen sehr
Lehrreich sein kann, wie  Sie  vieleicht
bemerkt haben.                          
Doch nun möchte ich noch ein paar Fragen
beanworten, die bei dem einen oder ande-
ren noch offen sind.                    
Die  im  Code  verwendete  Adresse $1c07
steht ursprünglich auf $3a.             
Dadurch,  daß sie auf $12 gesetzt wurde,
wird  bewirkt,  daß   der   Steppermotor
schneller reagiert, beim   Trackwechsel.
Dieser  Trick  ist  sehr  nützlich  bei 
vollen Disketten.                       
Die Zeropage-Adressen $30/$31  geben den
aktuellen Puffer an,  mit dem gearbeitet
werden soll.                            
Die  Port-Adresse  $1c01 ließt Bytes von
der Diskette.                           
Da  diese  Daten  noch GCR codiert sind,
reicht ein Puffer nicht  aus und der Be-
reich $01ba-$0200 wird mitbenutzt.   Mit
der Routine $f8e0 wird das ganze dann in
Normalcode umgewandelt.                 
Nun  sind  wir  am  Ende unseres Floppy-
kurses angelangt  und  ich  hoffe es hat
Ihnen  Spass  und  Freude bereit, in die
Wunderwelt der Floppyprogrammierung ein-
zutauchen.                              
           Es verabschiedet sich,       
                          Frank Boldewin



Valid HTML 4.0 Transitional Valid CSS!